package org.nativejpa.samples.firstapp;

import org.nativejpa.support.sqlgen.SQLGenerator;
import org.nativejpa.mapping.EntityFactory;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import java.util.HashMap;
import java.util.List;
import java.sql.Date;

/**
 * @author <a href="mailto:jfox.young@gmail.com">Young Yang</a>
 * @create 2009-8-19 14:27:49
 */
public class SampleDAO {

    public static final String SAMPLE_PERSITENCE_UNIT = "nativejpa_sample_persistence_unit";

    private EntityManagerFactory emf;
    private EntityManager em;

    public EntityManager getEntityManager() {
        if(em != null) {
            return em;
        }
        else {
            emf = Persistence.createEntityManagerFactory(SAMPLE_PERSITENCE_UNIT, new HashMap());
            em = emf.createEntityManager();
            return em;
        }
    }

    public void initDatabase(){
        System.out.println("Initialize Database...");
        Query query = getEntityManager().createNamedQuery(PersonEntity.NAMED_QUERY_CREATE_TABLE);
        query.executeUpdate();

        Query query2 = getEntityManager().createNamedQuery(AddressEntity.NAMED_QUERY_CREATE_TABLE);
        query2.executeUpdate();

        // init persons & addresses
        for(int i=0; i<10; i++) {
            PersonEntity person = EntityFactory.newEntityObject(PersonEntity.class);
            person.setId(i);
            person.setName("PERSON_" + i);
            person.setBirthDate(new Date(System.currentTimeMillis()));
            AddressEntity address = new AddressEntity();
            address.setId(i);
            address.setPersonId(person.getId());
            address.setName("ADDRESS_" + i);
            person.setAddress(address);
            // persist person,address by EntityManager.persist()
            getEntityManager().persist(person);
            getEntityManager().persist(address);
        }
        System.out.println("Initialize Database, DONE!");
    }

    public void showDatabase() {
        System.out.println("Display Database...");
        List<PersonEntity> allPerson = getEntityManager().createNativeQuery(SQLGenerator.buildSelectAllSQL(PersonEntity.class), PersonEntity.class).getResultList();
        printPersons(allPerson);
        System.out.println("Display Database, DONE!");
    }

    private void printPersons(List<PersonEntity> persons){
        System.out.println("PERSON_ID\tPERSON_NAME\t\tADDRESS(ID,NAME)");
        for(PersonEntity person : persons) {
            System.out.println(person.getId() + "\t\t\t" + person.getName() + "\t\t" + person.getAddress().getId() + "," + person.getAddress().getName());
        }
    }

    public PersonEntity getPersonById(long id) {
        PersonEntity person= (PersonEntity)getEntityManager().createNativeQuery(SQLGenerator.buildSelectByIdSQL(PersonEntity.class), PersonEntity.class).setParameter("ID",id).getSingleResult();
        return person;
    }

    public PersonEntity getPersonByName(String name) {
        PersonEntity person= (PersonEntity)getEntityManager().createNativeQuery(SQLGenerator.buildSelectByColumnSQL(PersonEntity.class, "NAME"), PersonEntity.class).setParameter("NAME",name).getSingleResult();
        return person;
    }

    public List<PersonEntity> getPersonsByAddress(long addressId){
        List<PersonEntity> persons = (List<PersonEntity>)getEntityManager().createNamedQuery(PersonEntity.NAMED_QUERY_SELECT_BY_CONDITION).setParameter("ADDRESS_ID", addressId).getResultList();
        printPersons(persons);
        return persons;
    }

    private void dropTables(){
        getEntityManager().createNativeQuery("DROP TABLE PERSON").executeUpdate();
        getEntityManager().createNativeQuery("DROP TABLE ADDRESS").executeUpdate();
    }

    public void close(){
        dropTables();
        try {
            Thread.sleep(1000);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        em.close();
        emf.close();
    }

}